//
//  "$Id: Ide.h 343 2008-04-09 04:03:43Z wang_haifeng $"
//
//  Copyright (c)1992-2007, ZheJiang Dahua Technology Stock CO.LTD.
//  All Rights Reserved.
//
//	Description:	
//	Revisions:		Year-Month-Day  SVN-Author  Modification
//

#ifndef __IDE_API_H__
#define __IDE_API_H__

#include "Types.h"
#include "Defs.h"
#include "list.h"

#ifdef __cplusplus
extern "C" {
#endif

/// \defgroup IDEAPI API IDE
/// 存储设备直接访问API，大华文件系统构建在此接口之上。 存储设备包括IDE硬盘，
///	SD Card等等，总线接口不限。
///	\n 调用流程图
/// \code
///    ===========================
///                |
///            ide_init
///                |
///         *ide_getinfo64
///                |------------+
///           ide_read64        |
///           ide_write64       |
///            ide_wakeup       |
///         ide_setstandby      |
///      ide_setstandby_multi   |
///                |------------+
///    ===========================
/// \endcode
/// @{

#define IDE_SECTOR_SIZE 512
#define IDE_SURPPORT_DISK 32
#ifndef IDE_SMART_INFO
#define IDE_SMART_INFO
/// IDE设备信息结构
typedef struct IDE_INFO64{
	/// 已挂载的硬盘的数量,，不包括坏盘。硬盘个数也等于ide_msk中置1的位个数减去
	/// ide_bad中置1的位个数. 应用程序访问硬盘时, 硬盘序号规则如下: 第一个被置1
	/// 的位对应的IDE通道上挂载的正常硬盘的硬盘序号为0，第二个被置1的位对应正常
	/// 硬盘的硬盘序号为1，依次类推。
	int		ide_num;

	///< IDE通道的数目，包括扩展的IDE通道。
	int		ide_port;

	/// 指示各个IDE通道上是否挂载硬盘，包括坏盘。每一位对应IDE通道的主盘或从盘，
	/// 置位表示以挂载硬盘，否则没有。对应关系为bit0对应IDE0的主盘，bit1对应IDE0
	/// 的从盘，bit2对应IDE1的主盘，bit3对应IDE1的从盘，依次类推。
	unsigned long	ide_msk;
	
	/// 指示各个IDE通道上是否挂载了坏的硬盘。每一位对应IDE通道的主盘或从盘，置位
	/// 表示以有坏硬盘，否则没有。对应关系同ide_msk。
	unsigned long	ide_bad;
	
	/// 已挂载的正常硬盘的容量，以扇区为单位，扇区大小为IDE_SECTOR_SIZE。扇区数用
	/// 32位来表示，数组下标是正常硬盘的序号。
	uint64			ide_cap[IDE_SURPPORT_DISK];
} IDE_INFO64, *pIDE_INFO64;

/// IDE详细信息
typedef struct IDE_DETAIL
{
	char device_mode[64];	// 设备模块，如"Hitachi HCT721010SLA360"
	char serial_number[32];	// 设备序列号，如"STH607MS2P8GAS"
	char firmware_version[16]; // 固件版本，如"ST6OA31E"
	char reserved[400]; 	// 保留
} IDE_DETAIL;

struct smart_attribute_individual
{
	uchar id;
	ushort flag;
	uchar attr;
	uchar worst;
	uchar threshold[6];
	uchar reserved;
};

struct smart_attribute
{
	ushort revision;
	struct smart_attribute_individual individual[30];
	uchar offline_data_collection_status;
	uchar vendor_spec1;
	ushort complete_offline_data_collection_activity;
	uchar vendor_spec2;
	uchar offline_data_collection_capability;
	ushort smart_capacity;
	uchar reserved[16];
	uchar vendor_spec3[125];
	uchar checksum;
};

struct threshold_attribute_individual
{
	uchar id;
	uchar threshold;
	uchar reserved[10];
};

struct threshold_attribute
{
	ushort revision;
	struct threshold_attribute_individual individual[30];
	uchar reserved[18];
	uchar vendor_spec[131];
	uchar chechsum;
};

struct smart_value
{
	uchar id;		///ID
	char *name;	///属性名
	uchar current;///属性值
	uchar worst;///最大出错值
	uchar threshold;///阈值
	char* raw;///实际值
	int predict;///状态
	struct list_head value;
};
#endif
/// 初始化所有IDE设备。
/// 
/// \param 无
/// \retval 0  操作成功
/// \retval <0  操作失败
int PAL_API ide_init(void);

/// 卸载所有IDE设备
///
/// \param 无
/// \retval 0  操作成功
/// \retval <0  操作失败
int PAL_API ide_unload(void);

/// 重新扫描IDE设备。
/// 
/// \param 无
/// \retval >=0 新扫描到的硬盘数。
/// \retval <0  失败
/// 仅返回增加的硬盘数，减少的情况下会与ide_getinfo64中的逻辑冲突，暂时没有添加。
int PAL_API ide_rescan(void);


/// 得到IDE的信息。
/// 
/// \param [out] info 指向用户申请的用来接收硬盘信息的结构IDE_INFO的指针。
/// \return>=0  硬盘数目
/// \retval <0  操作失败
int PAL_API ide_getinfo64(IDE_INFO64 *info);


/// 得到硬盘序号
/// 
/// \param [in] name 硬盘设备名称, 如: "/dev/hda", "/dev/sdb" ...
/// \retval >=0  硬盘序号
/// \retval <0  操作失败
int PAL_API ide_get_no(const char* name);


/// 读数据。因硬件故障而出错时, 应当设置硬盘信息中ide_bad对应的位, 但是
/// ide_num不应改变。
/// 
/// \param [in] dev 硬盘序号。
/// \param [in] sectors 要读出的扇区数。
/// \param [in] offs 读出点的扇区偏移。
/// \param [out] pdat 用来接收读出数据的缓冲。
/// \retval 0  操作成功
/// \retval -1 介质错误
/// \retval -2 总线错误
int PAL_API ide_read64(unsigned short dev, unsigned short sectors, uint64 offs, void * pdat);


/// 写数据。因硬件故障而出错时, 应当设置硬盘信息中ide_bad对应的位, 但是
/// ide_num不应改变。
/// 
/// \param [in] dev 硬盘序号。
/// \param [in] sectors 要写入的扇区数。
/// \param [in] offs 写入点的扇区偏移。
/// \param [in] pdat 待写入的数据的缓冲。
/// \retval 0  操作成功
/// \retval -1 介质错误
/// \retval -2 总线错误
int PAL_API ide_write64(unsigned short dev, unsigned short sectors, uint64 offs, void * pdat);

typedef struct IDE_IOVEC_t
{
	void  *iov_base;    /* Starting address */
	unsigned int iov_len;     	/* Number of bytes to transfer */
}IDE_IOVEC;
int PAL_API ide_multi_write64(unsigned short dev, unsigned short sectors, uint64 offs, IDE_IOVEC* iov, unsigned int iov_num);

/// 唤醒硬盘。如果硬盘处于活动状态，也要执行唤醒命令，保证不会在超时后自动进入
/// 睡眠状态。
/// 
/// \param [in] ide_no 硬盘序号。
/// \retval 0  操作成功
/// \retval <0  操作失败
int PAL_API ide_wakeup(unsigned short ide_no);


/// 设置待命时间，如果在这段时间内没有任何访问，硬盘自动进入睡眠状态。
/// 
/// \param [in] ide_no 硬盘序号。
/// \param [in] minutes 超时时间，分钟为单位。 
/// \retval 0  操作成功
/// \retval <0  操作失败
int PAL_API ide_setstandby(unsigned short ide_no,int minutes);


/// 同时设置多个硬盘的待命时间，以节约设置时间。
/// 
/// \param [in] ide_mask 硬盘掩码，定义和IDE_INFO中掩码定义相同。
/// \param [in] minutes 超时时间，分钟为单位。 
/// \retval 0  操作成功
/// \retval <0  操作失败
/// \see IDE_INFO
int PAL_API ide_setstandby_multi(unsigned long ide_mask, int minutes);


/// 获取SMART信息
int PAL_API ide_get_smart_attr(unsigned short ide_no, struct smart_attribute * attr);


/// 获取SMART阈值信息
int PAL_API ide_get_threshold_attr(unsigned short ide_no, struct threshold_attribute * attr);


///获取SMART信息
///获取SMART阈值信息
///解析SMART信息以及阈值信息
///@return -1:失败,0:成功
int PAL_API ide_get_smart_threshold_attr(unsigned short ide_no, struct smart_attribute *smart, struct threshold_attribute *threshold);

///获取解析后的smart信息,有30个提取到的信息,每次获取后必须调用destroy_smart_value释放该值
struct PAL_API smart_value *get_smart_value(void);

///释放smart 信息
void PAL_API destroy_smart_value(struct smart_value *value);


/// 获取指定硬盘的错误日志信息
/// \param [in] ide_no – sata接口序号
/// \param [out] errlog – 错误类型
///          -1: 无错误；-2: 传输错误；其它：介质错误，错误扇区号
/// \retval 0 – 成功
/// \retval -1 – 失败
int PAL_API ide_get_errlog(unsigned short ide_no, int *errlog);

/// 获取硬盘详细信息，比如设备模块，序列号，固件版本等等
int PAL_API ide_get_detail(unsigned short ide_no, IDE_DETAIL *detail);

/// 测试硬盘状态             
///
///\param[in]  dev 设备id号      
///\param[in]  offs 扇区偏移量 
///\return  = 0  正常= -1 运行错误   = -2 坏盘 
int  ide_diskstate(uint const dev, uint64 const offs);

///  打开测试硬盘速度开关          
void ide_s_diskspeed(void);

///   关闭测试硬盘速度开关 
void ide_d_diskspeed(void);

/// @} end of group

#ifdef __cplusplus
}
#endif

#endif //__IDE_API_H__

